const BASE_URL = import.meta.env.VITE_API_BASE || 'http://localhost:8080'

function mapErrorMessage(code, status, fallback) {
  const map = {
    AUTH_FAILED: '认证失败，请检查账号或密码',
    UNAUTHORIZED: '未登录或登录已过期，请重新登录',
    FORBIDDEN: '没有权限执行此操作',
    NOT_FOUND: '资源不存在',
    ORDER_NOT_OWNER: '仅本人或管理员可查看该订单',
    VALIDATION_ERROR: '参数校验失败，请检查填写内容',
    CONFLICT: '请求冲突，稍后再试',
    RATE_LIMITED: '请求过于频繁，请稍后重试'
  }
  if (code && map[code]) return map[code]
  if (status === 401) return map.UNAUTHORIZED
  if (status === 403) return map.FORBIDDEN
  if (status === 404) return map.NOT_FOUND
  return fallback || `HTTP ${status}`
}

function dispatchApiEvent(name, detail) {
  try {
    window.dispatchEvent(new CustomEvent(name, { detail }))
  } catch (_) {}
}

function getAuthToken() {
  // 会话优先，其次持久化
  return sessionStorage.getItem('token') || localStorage.getItem('token')
}

async function request(path, options = {}) {
  const token = getAuthToken()
  const isFormData = typeof FormData !== 'undefined' && options.body instanceof FormData
  const isBlob = typeof Blob !== 'undefined' && options.body instanceof Blob
  const headers = {
    ...(options.headers || {})
  }
  // 非上传且有请求体时，设置为 JSON；上传由浏览器自动设置边界
  if (!isFormData && !isBlob && options.method !== 'GET' && options.body && !headers['Content-Type']) {
    headers['Content-Type'] = 'application/json'
  }
  if (token) {
    headers['Authorization'] = `Bearer ${token}`
  }
  try {
    const res = await fetch(`${BASE_URL}${path}`, {
      ...options,
      headers
    })
    if (!res.ok) {
      let code
      let message = `HTTP ${res.status}`
      try {
        const data = await res.json()
        code = data?.code
        message = mapErrorMessage(code, res.status, data?.message || message)
      } catch (_) {
        message = mapErrorMessage(undefined, res.status, message)
      }
      if (res.status === 401) {
        // 清理失效令牌并通知需要登录
        localStorage.removeItem('token')
        dispatchApiEvent('auth-required', { status: res.status, code, message })
      }
      dispatchApiEvent('api-error', { status: res.status, code, message })
      const err = new Error(message)
      err.code = code
      err.status = res.status
      throw err
    }
    // 根据响应类型解析；若无响应体则返回 null
    const contentType = res.headers.get('content-type') || ''
    if (contentType.includes('application/json')) {
      try {
        return await res.json()
      } catch (_) {
        return null
      }
    }
    const text = await res.text()
    return text ? text : null
  } catch (error) {
    // 网络错误或解析错误
    const message = error?.message || '网络异常，请稍后重试'
    dispatchApiEvent('api-error', { status: 0, code: 'NETWORK_ERROR', message })
    throw error
  }
}

export const apiClient = {
  get(path) {
    return request(path, { method: 'GET' })
  },
  post(path, body) {
    return request(path, { method: 'POST', body: JSON.stringify(body) })
  },
  put(path, body) {
    return request(path, { method: 'PUT', body: JSON.stringify(body) })
  },
  delete(path) {
    return request(path, { method: 'DELETE' })
  },
  postUpload(path, formData) {
    const token = getAuthToken()
    const headers = {}
    if (token) headers['Authorization'] = `Bearer ${token}`
    return request(path, { method: 'POST', body: formData, headers })
  }
}

export { BASE_URL }